from flask import Flask, request, jsonify
import os
import json
import requests
import logging
from typing import Dict, Any, Optional, List, Tuple
import subprocess
from dotenv import load_dotenv
from config import Config
import traceback
import datetime
from werkzeug.utils import secure_filename

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = Flask(__name__)

class PDFImageProcessor:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.headers = {"Authorization": f"Bearer {api_key}"}


    def extract_images_from_pdfs(self, input_dir: str, output_dir: str) -> Dict:
        """
        从PDF文件中提取图片
        
        Args:
            input_dir: 输入目录
            output_dir: 输出目录
            
        Returns:
            Dict: 处理结果
        """
        os.makedirs(output_dir, exist_ok=True)
        
        results = []
        for filename in os.listdir(input_dir):
            if filename.lower().endswith('.pdf'):
                pdf_path = os.path.join(input_dir, filename)
                pdf_name = os.path.splitext(filename)[0]
                out_path = os.path.join(output_dir, pdf_name)
                os.makedirs(out_path, exist_ok=True)

                cmd = ['magic-pdf', '-p', pdf_path, '-o', out_path]
                logger.info(f"正在解析 PDF: {filename}")
                try:
                    subprocess.run(cmd, check=True)
                    logger.info(f"解析成功: {filename}")
                    results.append({"filename": filename, "status": "success"})
                except subprocess.CalledProcessError as e:
                    logger.error(f"解析失败: {filename}")
                    logger.error(e.stderr)
                    results.append({"filename": filename, "status": "failed", "error": str(e.stderr)})

        return {"success": True, "results": results}

    # def extract_images_from_pdfs(self, input_dir: str, output_dir: str) -> Dict:
    #     """
    #     获取已生成的图片
    #     """
    #     logger.info("直接使用已生成的图片")
    
    #     results = []
    #     # 直接检查输出目录中的图片
    #     for root, dirs, files in os.walk(output_dir):
    #         for file in files:
    #             if file.lower().endswith(('.jpg', '.jpeg', '.png')):
    #                 results.append({"filename": file, "status": "success"})
    
    #     return {"success": True, "results": results}
    
    def upload_images_via_http(self, output_dir: str, upload_url: str, bucket_name: str) -> Dict:
        """
        通过HTTP上传图片到MinIO
        """
        results = []
        for root, dirs, files in os.walk(output_dir):
            for file in files:
                if file.lower().endswith(('.jpg', '.jpeg', '.png')):
                    file_path = os.path.join(root, file)
                    try:
                        logger.info(f"正在处理文件: {file_path}")
                        logger.info(f"文件大小: {os.path.getsize(file_path)} 字节")
                        if not os.path.exists(file_path):
                            logger.error(f"文件不存在: {file_path}")
                            results.append({"filename": file, "status": "failed", "error": "文件不存在"})
                            continue
                        if not os.access(file_path, os.R_OK):
                            logger.error(f"文件不可读: {file_path}")
                            results.append({"filename": file, "status": "failed", "error": "文件不可读"})
                            continue
                        
                        with open(file_path, 'rb') as f:
                            try:
                                # 添加MIME类型
                                files = {'file': (file,f,'image/jpeg')}
                                
                                # 构建请求头
                                
                                logger.info(f"准备上传到: {upload_url}")
                                logger.info(f"使用存储桶: {bucket_name}")
                                response = requests.post(
                                    upload_url,
                                    files=files
                                )
                                
                                response.raise_for_status()
                                logger.info(f"图片上传成功: {file}")
                                logger.info(f"响应内容: {response.json()}")
                                results.append({"filename": file, "status": "success"})
                                
                            except Exception as e:
                                logger.error(f"上传失败: {file}")
                                logger.error(f"文件路径: {file_path}")
                                # logger.error(f"上传URL: {upload_url}")
                                logger.error(f"存储桶: {bucket_name}")
                                logger.error(f"错误详情: {str(e)}")
                                results.append({"filename": file, "status": "failed", "error": str(e)})
                    except Exception as e:
                        logger.error(f"处理文件失败: {file}")
                        logger.error(f"错误详情: {str(e)}")
                        results.append({"filename": file, "status": "failed", "error": str(e)})
    
        return {"success": True, "results": results}

# @app.route('/process_images', methods=['POST'])
# def process_images():
#     """处理图片接口"""
#     try:
#         data = request.get_json()
#         api_key = data.get('api_key')
#         if not api_key:
#             return jsonify({'error': 'Missing api_key'}), 400

#         processor = PDFImageProcessor(api_key)
        
#         # 提取图片
#         extract_result = processor.extract_images_from_pdfs(
#             Config.INPUT_DIR,
#             Config.OUTPUT_DIR
#         )

#         # 上传图片
#         upload_result = processor.upload_images_via_http(
#             Config.OUTPUT_DIR,
#             Config.API_CONFIG['upload_url'],
#             Config.MINIO_CONFIG['bucket_name']
#         )

#         return jsonify({
#             'success': True,
#             'extract_result': extract_result,
#             'upload_result': upload_result
#         })

#     except Exception as e:
#         logger.error(f"Error processing images: {str(e)}")
#         return jsonify({'error': str(e)}), 500

@app.route('/upload_file', methods=['POST'])
def upload_file():
    """接收文件流并保存到本地"""
    try:
        # 检查请求头
        auth_header = request.headers.get('Authorization')
        if not auth_header or not auth_header.startswith('Bearer '):
            return jsonify({'error': 'Missing or invalid Authorization header'}), 401

        # 获取文件
        file = request.files.get('file')
        if not file:
            return jsonify({'error': 'No file provided'}), 400

        # 获取原始文件名
        filename = file.filename
        if not filename.lower().endswith('.pdf'):
            return jsonify({'error': 'Only PDF files are allowed'}), 400

        # 检查目录配置
        logger.info(f"Input directory: {Config.INPUT_DIR}")
        logger.info(f"Output directory: {Config.OUTPUT_DIR}")
        
        # 保存到本地目录
        save_path = os.path.join(Config.INPUT_DIR, filename)
        os.makedirs(Config.INPUT_DIR, exist_ok=True)
        
        # 检查目录是否可写
        if not os.access(Config.INPUT_DIR, os.W_OK):
            return jsonify({'error': f'Cannot write to directory: {Config.INPUT_DIR}'}), 500

        logger.info(f"Saving file to: {save_path}")
        file.save(save_path)
        
        # 检查文件是否保存成功
        if not os.path.exists(save_path):
            return jsonify({'error': f'Failed to save file: {save_path}'}), 500

        # 检查文件大小
        file_size = os.path.getsize(save_path)
        logger.info(f"File size: {file_size} bytes")
        if file_size == 0:
            return jsonify({'error': 'Empty file received'}), 400

        # 调用 PDFImageProcessor 处理文件
        processor = PDFImageProcessor(auth_header.replace('Bearer ', ''))
        
        # 检查 magic-pdf 命令是否存在
        try:
            subprocess.run(['which', 'magic-pdf'], check=True)
        except subprocess.CalledProcessError:
            return jsonify({'error': 'magic-pdf command not found'}), 500

        result = processor.extract_images_from_pdfs(Config.INPUT_DIR, Config.OUTPUT_DIR)

        # 上传图片
        upload_result = processor.upload_images_via_http(
            Config.OUTPUT_DIR,
            Config.API_CONFIG['upload_url'],
            Config.MINIO_CONFIG['bucket_name']
        )
        
        return jsonify({
            'success': True,
            'filename': filename,
            'save_path': save_path,
            'file_size': file_size,
            'processing_result': result,
            'upload_result': upload_result
        })


    except Exception as e:
        logger.error(f"Error uploading file: {str(e)}")
        logger.error(f"Traceback: {traceback.format_exc()}")        
        return jsonify({
            'error': str(e),
            'details': {
                'timestamp': datetime.datetime.now().isoformat(),
                'error_type': type(e).__name__
            }
        }), 500

# @app.route('/process_images', methods=['POST'])
# def process_images():
#     """处理图片接口"""
#     try:
#         data = request.get_json()
#         api_key = data.get('api_key')
#         if not api_key:
#             return jsonify({'error': 'Missing api_key'}), 400

#         processor = PDFImageProcessor(api_key)
        
#         # 直接使用输出目录中的图片
#         logger.info("开始上传已生成的图片...")
        
#         # 上传图片
#         upload_result = processor.upload_images_via_http(
#             Config.OUTPUT_DIR,  # 直接使用输出目录
#             Config.API_CONFIG['upload_url'],
#             Config.MINIO_CONFIG['bucket_name']
#         )

#         return jsonify({
#             'success': True,
#             'upload_result': upload_result
#         })

#     except Exception as e:
#         logger.error(f"Error processing images: {str(e)}")
#         return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    app.run(
        host='127.0.0.1',
        port=18005,
        debug=Config.DEBUG
    )
